package org.gpp.proj1.ui.gui.shop;

import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.Map;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.gpp.proj1.logic.metadata.PartCategory;
import org.gpp.proj1.logic.metadata.PartEntry;
import org.gpp.proj1.ui.gui.SRGGUIView;
import org.gpp.proj1.ui.gui.command.SRGGUICommandFactory;

/**
 * @author Paolo Victor, paolovictor@gmail.com
 */
public class BuyPartsWindow extends JFrame implements ListSelectionListener, ChangeListener {

	private static final long serialVersionUID = 2361863524540580309L;

	private JButton buyButton;
	private JLabel cashLabel;
	private JList partsListArm;
	private JScrollPane jScrollPane1;
	private JScrollPane jScrollPane2;
	private JSeparator jSeparator1;
	private JSpinner numParts;
	private JTabbedPane partsTabbedPanel;
	private JTextArea partDescription;
	private JLabel partLabel;
	private JLabel partPictureLabel;
	private JLabel unitLabel;

	private Map<PartCategory, JList> partLists;

	private final SRGGUIView view;

	private String selectedPart;

	private PartCategory selectedCategory;

	private Map<PartCategory, Map<String, PartEntry>> partsMap;

	public BuyPartsWindow( SRGGUIView view ) {
		this.view = view;
		this.partLists = new HashMap<PartCategory, JList>();

		this.initComponents();
	}

	private void initComponents() {
		partsTabbedPanel = new javax.swing.JTabbedPane();
		jScrollPane1 = new javax.swing.JScrollPane();
		partsListArm = new javax.swing.JList();
		buyButton = new javax.swing.JButton();
		numParts = new javax.swing.JSpinner();
		unitLabel = new javax.swing.JLabel();
		partLabel = new javax.swing.JLabel();
		partPictureLabel = new javax.swing.JLabel();
		jScrollPane2 = new javax.swing.JScrollPane();
		partDescription = new javax.swing.JTextArea();
		cashLabel = new javax.swing.JLabel();
		jSeparator1 = new javax.swing.JSeparator();

		setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
		setResizable(false);

		SpinnerNumberModel spinnerModel = new SpinnerNumberModel();
		spinnerModel.setMinimum( 1 );
		spinnerModel.setMaximum( 99 );
		spinnerModel.setValue( 1 );

		numParts.setModel( spinnerModel );
		numParts.addChangeListener( this );
		numParts.setEnabled( false );

		jScrollPane1.setViewportView(partsListArm);

		buyButton.setText("Buy");
		buyButton.setEnabled( false );
		buyButton.setActionCommand( SRGGUICommandFactory.BUY_PART_COMMAND );
		buyButton.addActionListener( view );

		unitLabel.setText("");

		partLabel.setFont(new java.awt.Font("Dialog", 1, 14));
		partLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
		partLabel.setText("");

		partPictureLabel.setBackground(new java.awt.Color(255, 255, 255));
		partPictureLabel.setText("");
		partPictureLabel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
		partPictureLabel.setOpaque(true);

		partDescription.setColumns(20);
		partDescription.setEditable(false);
		partDescription.setRows(5);
		partDescription.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
		jScrollPane2.setViewportView(partDescription);

		cashLabel.setFont(new java.awt.Font("Dialog", 1, 18));
		this.setCash( view.getController().getCurrentProfile().getCash() );


		org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(
				layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
				.add(layout.createSequentialGroup()
						.addContainerGap()
						.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
								.add(cashLabel)
								.add(jSeparator1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 578, Short.MAX_VALUE)
								.add(layout.createSequentialGroup()
										.add(partsTabbedPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 226, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
										.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
												.add(partLabel, 0, 0, Short.MAX_VALUE)
												.add(partPictureLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)
												.add(layout.createSequentialGroup()
														.add(buyButton)
														.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
														.add(numParts, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 42, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
														.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
														.add(unitLabel))
														.add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE))))
														.addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);
		layout.setVerticalGroup(
				layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
				.add(layout.createSequentialGroup()
						.addContainerGap()
						.add(cashLabel)
						.add(11, 11, 11)
						.add(jSeparator1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 10, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
						.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
								.add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
										.add(partLabel)
										.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
										.add(partPictureLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 124, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
										.add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 276, Short.MAX_VALUE))
										.add(partsTabbedPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 429, Short.MAX_VALUE))
										.addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
										.add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
												.add(buyButton)
												.add(numParts, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
												.add(unitLabel))
												.addContainerGap())
		);
		pack();

		partsTabbedPanel.addChangeListener( this );

		this.loadPartList();
		this.setLocationRelativeTo( null );
	}                     

	private void loadPartList() {
		
		this.partsMap = this.view.getController().getPartsList();

		for( PartCategory category : partsMap.keySet() ) {
			JScrollPane categoryPane = new JScrollPane();

			JList partsList = new JList();
			DefaultListModel model = new DefaultListModel();
			partsList.setModel( model );

			partsList.addListSelectionListener( this );
			partsList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );

			for( String entry : partsMap.get( category ).keySet() ) {
				PartEntry partEntry = partsMap.get( category ).get( entry );
				model.addElement( partEntry.getName() );
			}

			this.partLists.put( category, partsList );

			categoryPane.setViewportView( partsList );
			partsTabbedPanel.addTab( category.name(), categoryPane );
		}
	}

	private void setCash(int cash) {

		cashLabel.setText("Cash: " + cash + "\u00a2");
	}

	public void valueChanged(ListSelectionEvent e) {
		int index = partsTabbedPanel.getModel().getSelectedIndex();
		PartCategory category = PartCategory.valueOf( partsTabbedPanel.getTitleAt( index) );

		JList partList = partLists.get( category );
		
		if( partList.getSelectedIndex() == -1 ) {
			return;
		}

		if( ! partLists.containsKey( category ) ) {
			throw new InvalidParameterException( "Invalid category: \"" + category + "\"" );
		}

		this.selectedCategory = category;
		this.selectedPart = (String) partList.getModel().getElementAt( partList.getSelectedIndex() );

		PartEntry part = this.partsMap.get( category ).get( selectedPart );

		partLabel.setText( part.getName() );		
		unitLabel.setText("unit(s) for " + (part.getPrice() * (Integer)numParts.getValue()) + "\u00a2" );

		this.partDescription.setText( part.getPartDescription() );
		this.buyButton.setEnabled( true );		
		this.numParts.setEnabled( true );
	}

	public void stateChanged(ChangeEvent e) {

		if( e.getSource() == partsTabbedPanel ) { 
			for( PartCategory category : partLists.keySet() ) {
				partLists.get( category ).clearSelection();
			}

			this.buyButton.setEnabled( false );
			this.numParts.setEnabled( false );
			this.unitLabel.setText( "" );
			this.partDescription.setText( "" );
			this.partLabel.setText( "" );
		} else {		
			if( selectedCategory != null && selectedPart != null ) {
				PartEntry entry = partsMap.get( selectedCategory ).get( selectedPart );
				unitLabel.setText("unit(s) for " + (entry.getPrice() * (Integer)numParts.getValue()) + "\u00a2" );
			}
		}		
	}

	public PartCategory getSelectedCategory() {

		return selectedCategory;
	}

	public String getSelectedPart() {

		return selectedPart;
	}

	public int getPartQuantity() {

		return (Integer) numParts.getModel().getValue();
	}

	public void updatePlayerData() {

		this.setCash( view.getController().getCurrentProfile().getCash() );
	}
}
